<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
<script>

    /*
       由于 var 有变量提升 ： 浏览器会先扫描js（先解析后使用），作出预编译（统计所有的变量、函数），并对代码进行压缩、
       去注释空白等，这样的好处是每次执行函数时能直接分配栈空间，不需要再解析一次
     */
    a = 1
    var a
    console.log(a) // 1

    b = 2
    let b
    console.log(b)  //  Uncaught ReferenceError: Cannot access 'b' before initialization

    console.log(c)  // undefined   变量提升指的是变量声明的提升，不会提升变量的初始化和赋值。
    var c = 3

    /*
   这里确实出现了变量提升，而我们不能够访问的原因事实上是因为let的死区（temporal dead zone）设计：
   当前作用域顶部到该变量声明位置中间的部分，都是该let变量的死区，在死区中，禁止访问该变量。
   由此，我们给出结论，let声明的变量存在变量提升， 但是由于死区我们无法在声明前访问这个变量。
     */
    let w = "hey I am outside"
    if (true) {
        console.log(w)  //Uncaught ReferenceError: w is not defined
        let w = "hey I am inside"
    }

    // 函数也是存在提升（hoisting）的，并且，函数的提升不同于变量的提升，函数相当于把自己的声明、赋值整个的放到了当前作用域的顶部。
</script>
</body>
</html>
